﻿using System;
using System.Linq;
using System.Xml.Linq;
using Caliburn.Micro;
using SunXmlEditor.Views;

namespace SunXmlEditor
{
  public class SunXElementViewModel : Screen
  {
    public SunXElementViewModel(XElement xe, SunXElementViewModel ancestor = null)
    {
      _Element = xe;
      _Ancestor = ancestor;
      _Descendants = new Lazy<BindableCollection<SunXElementViewModel>>(LoadDescendants);
      _Attributes = new Lazy<BindableCollection<SunXAttribute>>(LoadAttributes);
    }

    private readonly IWindowManager _WindowManager = IoC.Get<IWindowManager>();
    private readonly IEventAggregator _EventAggregator = IoC.Get<IEventAggregator>();
    private readonly XElement _Element;
    private readonly SunXElementViewModel _Ancestor;

    private readonly Lazy<BindableCollection<SunXElementViewModel>> _Descendants;
    private readonly Lazy<BindableCollection<SunXAttribute>> _Attributes;

    /// <summary>
    /// 获取展示名。
    /// 只读，写异常。
    /// </summary>
    public override string DisplayName
    {
      get => $"[{ElementName}] {ElementTitle}";
      set => throw new NotSupportedException();
    }

    /// <summary>
    /// 获取节点名。
    /// </summary>
    public string ElementName => _Element.Name.LocalName;

    /// <summary>
    /// 获取节点标题名。
    /// </summary>
    public string ElementTitle => _Element.Attribute("Name")?.Value;

    #region 绑定数据

    /// <summary>
    /// 子集后代节点
    /// </summary>
    public BindableCollection<SunXElementViewModel> Descendants => _Descendants.Value;

    /// <summary>
    /// 节点特性数据列表
    /// </summary>
    public BindableCollection<SunXAttribute> Attributes => _Attributes.Value;

    private SunXAttribute _SelectedAttribute;

    /// <summary>
    /// 绑定通知，当前选中的节点特性
    /// </summary>
    public SunXAttribute SelectedAttribute
    {
      get { return _SelectedAttribute; }
      set
      {
        if (_SelectedAttribute == value) { return; }
        _SelectedAttribute = value;
        NotifyOfPropertyChange(nameof(SelectedAttribute));
      }
    }

    #endregion 绑定数据

    #region 绑定方法

    public void AddAttribute()
    {
      var screen = new AddNameValuePairViewModel();
      if (true == _WindowManager.ShowDialog(screen))
      {
        try
        {
          var xa = new XAttribute(screen.XName, screen.XValue);
          _Element.Add(xa);
          Attributes.Add(new SunXAttribute(_Element, xa));
        }
        catch (Exception ex)
        {
          _EventAggregator.PublishOnUIThread(new ErrorMessage(ex, "添加特性异常。"));
        }
      }
    }

    public void DeleteAttribute()
    {
      if (null == SelectedAttribute) return;
      SelectedAttribute.Delete();
      Attributes.Remove(SelectedAttribute);
    }

    #endregion 绑定方法

    private BindableCollection<SunXElementViewModel> LoadDescendants()
    {
      var dQuery = from dd in _Element.Elements()
                   select new SunXElementViewModel(dd, this);
      return new BindableCollection<SunXElementViewModel>(dQuery);
    }

    private BindableCollection<SunXAttribute> LoadAttributes()
    {
      var dQuery = from dd in _Element.Attributes()
                   select new SunXAttribute(_Element, dd);
      return new BindableCollection<SunXAttribute>(dQuery);
    }

    /// <summary>
    /// 添加子集节点。
    /// </summary>
    /// <param name="elementName">节点名</param>
    internal void AddElement(string elementName)
    {
      var xe = new XElement(elementName);
      _Element.Add(xe);
      Descendants.Add(new SunXElementViewModel(xe, this));
    }

    /// <summary>
    /// 删除本节点，之后从展示数据列表中移除。
    /// </summary>
    internal void Delete()
    {
      _Element.Remove();
      _Ancestor?.Descendants.Remove(this);
    }

    public override string ToString()
    {
      return DisplayName;
    }
  }
}